In [1]:
# importamos bibliotecas cómputo de matrices
import numpy as np

# importamos bibliotecas para plotear
import matplotlib
import matplotlib.pyplot as plt

# para desplegar los plots en el notebook
%matplotlib inline

Matriz de Leslie

La Matriz de Leslie se usa en ecología para modelar los cambios en una población de organismos a través de un lapso. En este modelo la población se divide en grupos de edad. Para cada unidad de tiempo la población se representa con un vector con un elemento por cada clase de edad.

Se trata de una matriz cuadrada con tantos renglones y columnas como el vector de clases tiene elementos.

$$ L=\left[\begin{array}{cccc} 0 & 1 & 2 & 1\\ 0.8 & 0 & 0 & 0\\ 0 & 0.7 & 0 & 0\\ 0 & 0 & 0.5 & 0 \end{array}\right] $$

In [2]:
# el modelo de Leslie
L = np.array([[0,     1,  2],
              [0.8,   0,  0],
              [0,   0.7,  0]])

# las cuatro clases de edad tienen 100 pobladoras al inicio
poblacion_inicial = [100,100,100]

# lista para contener un vector de tamaños de población por clase para
# cada unidad de tiempo transcurrida en la simulación. Inicializamos con
# la poblacion inicial en el tiempo cero.
historico_de_poblaciones  = [ poblacion_inicial, ]


# en otra lista guardaremos las proporciones de cada clase respecto del
# total de la población.
historico_de_proporciones = []

Al paso del tiempo

En cada paso de tiempo el vector de clases de población se multiplica por la matriz Leslie para generar el vector del siguiente paso.


In [3]:
# iteramos 25 veces
for t in range(25):
    # nuevo vector
    vector_de_clases = np.dot(L, historico_de_poblaciones[t])
    # al histórico
    historico_de_poblaciones.append( vector_de_clases )
    
    poblacion_total        = vector_de_clases.sum()
    vector_de_proporciones = [clase/poblacion_total for clase in vector_de_clases]
    historico_de_proporciones.append( vector_de_proporciones )

Tamaños de clases de poblaciones

Al Paso del tiempo las poblaciones crecen.


In [4]:
np.array( historico_de_poblaciones[0:10] )


Out[4]:
array([[  100.    ,   100.    ,   100.    ],
       [  300.    ,    80.    ,    70.    ],
       [  220.    ,   240.    ,    56.    ],
       [  352.    ,   176.    ,   168.    ],
       [  512.    ,   281.6   ,   123.2   ],
       [  528.    ,   409.6   ,   197.12  ],
       [  803.84  ,   422.4   ,   286.72  ],
       [  995.84  ,   643.072 ,   295.68  ],
       [ 1234.432 ,   796.672 ,   450.1504],
       [ 1696.9728,   987.5456,   557.6704]])

In [5]:
figura = plt.plot( historico_de_poblaciones[0:10] )



In [6]:
figura = plt.plot( historico_de_poblaciones )


Proporciones de tamaños de clases de poblaciones

Pero el tamaño proporcional de las clases de subpoblación se estabiliza.


In [7]:
np.array( historico_de_proporciones[10:20] )


Out[7]:
array([[ 0.5100068 ,  0.31311847,  0.17687473],
       [ 0.51533147,  0.31529188,  0.16937666],
       [ 0.50818782,  0.32032671,  0.17148547],
       [ 0.51256444,  0.31416244,  0.17327312],
       [ 0.51190984,  0.31770344,  0.17038673],
       [ 0.51029009,  0.31736575,  0.17234415],
       [ 0.51225044,  0.315861  ,  0.17188856],
       [ 0.51113296,  0.31754147,  0.17132557],
       [ 0.51123111,  0.31664343,  0.17212546],
       [ 0.51171443,  0.31666705,  0.17161852]])

In [8]:
figura = plt.plot( historico_de_proporciones )


Eigenvector, eigenvalor

$$P_{t+1}=(1+q)P_{t}$$$$P_{t}=P_{0}(1+q)^{t}$$

Distribución de proporciones $\overrightarrow{Q^{*}}$

$$\overrightarrow{Q^{*}}=\left[\begin{array}{c} q_{1}^{*}\\ q_{2}^{*}\\ q_{3}^{*} \end{array}\right]$$

para $t$ grande

$$\overrightarrow{X_{t+1}}=\overrightarrow{P_{t+1}}\left[\begin{array}{c} q_{1}^{*}\\ q_{2}^{*}\\ q_{3}^{*} \end{array}\right]=(1+q)P_{t}\overrightarrow{Q^{*}}=\overrightarrow{X_{t}}(1+q)$$

por otro lado

$\overrightarrow{X_{t+1}}=L\overrightarrow{X_{t}}=\lambda\overrightarrow{X_{t}}$

donde $\lambda=1+q$

$P_{t}=P_{0}(1+q)^{t}\Longleftrightarrow P_{t}=P_{0}e^{rt}$, $r=ln(1+q)$

Aspiramos a que en general el modelo de Leslie implique que la distribución de proporciones en clases de edad se estabilice, en cuyo caso si $x\rightarrow\infty$, $L\overrightarrow{X_{t}}=\lambda\overrightarrow{X_{t}}$

Definición

Sea $M$ una matriz $nxn$, se dice $\overrightarrow{X}$ es un vector propio de $M$ si y sólo si existe lamba en C tal que $M\overrightarrow{X}=\lambda\overrightarrow{X}$. El escalar $\lambda$ es un valor propio del vector $\overrightarrow{X}$ propio de $M$.

Qué conveniente poder multiplicar por un escalar y no por una matriz.

(1) $M\overrightarrow{X}=\lambda\overrightarrow{X}$ que es equivalente a $\lambda\overrightarrow{X}-M\overrightarrow{X}=0$

Usemos una matriz identidad como neutro multiplicativo para tener $\lambda\overrightarrow{X}$


In [9]:
# lmbd = np.linalg.det(L)
v = np.linalg.eig(L)[1][:,0]
l=sum(v)
v/l


Out[9]:
array([ 0.51140266+0.j,  0.31683815+0.j,  0.17175920+0.j])

Método de newton

Vamos sacando la derivada de la función para con esa llegar a X.

Encontramos la raíz por ahí de 1.2912


In [10]:
def p(x):
    return (x*x*x)-(0.8*x)-1.12

# derivada de p
def pp(x):
    return (3*x*x)-0.8

def N(x):
    return x - (p(x)/pp(x))

j = []
x = 1

for n in range(15):
    x = N(x)
    j.append(x)
    
j


Out[10]:
[1.4181818181818182,
 1.3039689466672792,
 1.2914116724570692,
 1.2912653875463846,
 1.2912653678175081,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077,
 1.2912653678175077]